package rtmp;

import io.netty.buffer.Unpooled;
import org.apache.log4j.Logger;
import util.Common;
import util.MsgType;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;

public class RtmpResponse {

    private final static Logger logger = Logger.getLogger(RtmpResponse.class);

    /**
     *
     * @param ctx
     * @param chunkLength 新的 chunkLength
     * @param chunkSize 旧的，发送给客户端得旧的chunkSize
     */
    // 服务器 告诉客户端，自己是使用 多大的 chunk 大小
    public static void responseChunkSize(ChannelHandlerContext ctx,int chunkLength,int chunkSize) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(1024);
        byte[] data = Common.int2Bytes(chunkLength);
        byteBuf.writeBytes(data);
        int length2 = byteBuf.readableBytes();
        byte[] beginData2 = new byte[length2];
        byteBuf.readBytes(beginData2);
        RtmpResponse.sendData(beginData2, MsgType.MSG_CHUNK_SIZE, 0, ctx, 0,chunkSize);
        byteBuf.release();
    }

     // sendData 是 chunk设置了长度之后的返回，  发送端 跟 接收方的chunksize 不一致，需要重新修改，暂时还没修改
    private static int sendChunkLength = Common.DEFAULT_CHUNK_MESSAGE_LENGTH;
    public static void sendData(byte[] chunkData, byte msgType, int streamId, ChannelHandlerContext ctx, int timestamp,int chunkLength) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(1024);
        byte flags;
        if (streamId == Common.STREAM_ID) {
            flags = (4 & 0x3f) | (0 << 6);
        } else {
            flags = (3 & 0x3f) | (0 << 6);
        }
//        byte stream = (byte) ((streamId >> 24) & 0xff);
//        flags = (byte) ((stream & 0x3f) | (0 << 6));
        //  byte[] timestamp = {0x00,0x00,0x00};
        if (chunkData == null) {
            return;
        }
        int msg_len = chunkData.length;
//        logger.error("responseLength == " + msg_len);
        byte[] msgLength = Common.reverseArray(Common.intToByte24(msg_len));
        byte[] streamData = Common.intToByte(streamId);
        byteBuf.writeByte(flags);
        if(timestamp >= Common.TIMESTAMP_MAX_NUM){
            byteBuf.writeBytes(new byte[]{(byte)0xff,(byte) 0xff,(byte) 0xff});
        } else {
            byteBuf.writeBytes(Common.reverseArray(Common.intToByte24(timestamp)));
        }
        byteBuf.writeBytes(msgLength);
        byteBuf.writeByte(msgType);
        byteBuf.writeBytes(streamData);
        if(timestamp >= Common.TIMESTAMP_MAX_NUM){
            System.out.println("下发额外时间戳" + timestamp);
            byteBuf.writeBytes(Common.reverseArray(Common.intToByte(timestamp)));
        }
        int pos = 0;
        while (pos < chunkData.length) {
            if (byteBuf.writableBytes() < chunkData.length) {
                byteBuf.ensureWritable(chunkData.length);
            }
            if (chunkData.length - pos < chunkLength) {
                for (int i = pos; i < chunkData.length; i++) {
                    byteBuf.writeByte(chunkData[i]);
                }
            } else {
                if (byteBuf.writableBytes() < pos + chunkLength) {
                    byteBuf.ensureWritable(pos + chunkLength);
                }
                for (int i = pos; i < pos + chunkLength; i++) {
                    byteBuf.writeByte(chunkData[i]);
                }

                if (pos + chunkLength != chunkData.length) {
                    if (streamId == Common.STREAM_ID) {
                        byteBuf.writeByte((byte) ((4 & 0x3f) | (3 << 6)));
                    } else {
                        byteBuf.writeByte((byte) ((3 & 0x3f) | (3 << 6)));
                    }
                }
//                if (streamId == Common.STREAM_ID) {
//                    byteBuf.writeByte((byte) ((4 & 0x3f) | (3 << 6)));
//                } else {
//                    byteBuf.writeByte((byte) ((3 & 0x3f) | (3 << 6)));
//                }
            }
            pos += chunkLength;
        }
        sendClient(ctx,byteBuf);
//        int sendLength = byteBuf.readableBytes();
//        byte[] sendData = new byte[sendLength];
//        byteBuf.readBytes(sendData);
//        ctx.writeAndFlush(Unpooled.copiedBuffer(sendData));
//
//        byteBuf.release();
    }


    /**
     * 当时间戳大于最大值，发送额外时间戳信息
     * @param chunkData
     * @param msgType
     * @param streamId
     * @param ctx
     * @param timestamp
     * @param chunkLength
     */
    public static void sendDataExtTimestamp(byte[] chunkData, byte msgType, int streamId, ChannelHandlerContext ctx, int timestamp,int chunkLength) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(1024);
        byte flags;
        if (streamId == Common.STREAM_ID) {
            flags = ((4 & 0x3f) | (0 << 6)) | 0x40;
        } else {
            flags = ((3 & 0x3f) | (0 << 6)) | 0x40;
        }
        //  byte[] timestamp = {0x00,0x00,0x00};
        int msg_len = chunkData.length;
//        logger.error("responseLength == " + msg_len);
        byte[] msgLength = Common.reverseArray(Common.intToByte24(msg_len));
        byte[] streamData = Common.intToByte(streamId);
        byteBuf.writeByte(flags);
        if(timestamp >= Common.TIMESTAMP_MAX_NUM){
            byteBuf.writeBytes(new byte[]{(byte)0xff,(byte) 0xff,(byte) 0xff});
        } else {
            byteBuf.writeBytes(Common.reverseArray(Common.intToByte24(timestamp)));
        }
        byteBuf.writeBytes(msgLength);
        byteBuf.writeByte(msgType);
//        byteBuf.writeBytes(streamData);
        if(timestamp >= Common.TIMESTAMP_MAX_NUM){
            System.out.println("下发额外时间戳" + timestamp);
            byteBuf.writeBytes(Common.reverseArray(Common.intToByte(timestamp)));
        }
        int pos = 0;
        while (pos < chunkData.length) {
            if (byteBuf.writableBytes() < chunkData.length) {
                byteBuf.ensureWritable(chunkData.length);
            }
            if (chunkData.length - pos < chunkLength) {
                for (int i = pos; i < chunkData.length; i++) {
                    byteBuf.writeByte(chunkData[i]);
                }
            } else {
                if (byteBuf.writableBytes() < pos + chunkLength) {
                    byteBuf.ensureWritable(pos + chunkLength);
                }
                for (int i = pos; i < pos + chunkLength; i++) {
                    byteBuf.writeByte(chunkData[i]);
                }

                if (pos + chunkLength != chunkData.length) {
                    if (streamId == Common.STREAM_ID) {
                        byteBuf.writeByte((byte) ((4 & 0x3f) | (3 << 6)));
                    } else {
                        byteBuf.writeByte((byte) ((3 & 0x3f) | (3 << 6)));
                    }
                }
//                if (streamId == Common.STREAM_ID) {
//                    byteBuf.writeByte((byte) ((4 & 0x3f) | (3 << 6)));
//                } else {
//                    byteBuf.writeByte((byte) ((3 & 0x3f) | (3 << 6)));
//                }
            }
            pos += chunkLength;
        }
        sendClient(ctx,byteBuf);
//        int sendLength = byteBuf.readableBytes();
//        byte[] sendData = new byte[sendLength];
//        byteBuf.readBytes(sendData);
//        ctx.writeAndFlush(Unpooled.copiedBuffer(sendData));
//
//        byteBuf.release();
    }



//    /**
//     * 同意数据发送
//     *
//     * @param chunkData
//     * @param msgType
//     * @param streamId
//     * @param ctx
//     */
//    public static void sendData2(byte[] chunkData, byte msgType, int streamId, ChannelHandlerContext ctx, int timestamp) {
//        ByteBuf streamByteBuf = ByteBufAllocator.DEFAULT.buffer(1024);
////        System.out.println(sendChunkLength);
//        byte flags;
//        if (streamId == Common.STREAM_ID) {
//            flags = (4 & 0x3f) | (0 << 6);
//        } else {
//            flags = (3 & 0x3f) | (0 << 6);
//        }
//        //  byte[] timestamp = {0x00,0x00,0x00};
//        int msg_len = chunkData.length;
//        byte[] msgLength = Common.reverseArray(Common.intToByte24(msg_len));
//        byte[] streamData = Common.intToByte(streamId);
//        streamByteBuf.writeByte(flags);
//        //  System.out.println(Common.bytes2hex(Common.reverseArray(Common.intToByte24(timestamp))));
//        streamByteBuf.writeBytes(Common.reverseArray(Common.intToByte24(timestamp)));
//        streamByteBuf.writeBytes(msgLength);
//        streamByteBuf.writeByte(msgType);
//        streamByteBuf.writeBytes(streamData);
//        int pos = 0;
//
//        while (pos < chunkData.length) {
//            if (streamByteBuf.writableBytes() < chunkData.length) {
//                streamByteBuf.ensureWritable(chunkData.length);
//            }
//            if (chunkData.length - pos < sendChunkLength) {
//                for (int i = pos; i < chunkData.length; i++) {
//                    streamByteBuf.writeByte(chunkData[i]);
//                }
//            } else {
//                if (streamByteBuf.writableBytes() < pos + sendChunkLength) {
//                    streamByteBuf.ensureWritable(pos + sendChunkLength);
//                }
//                for (int i = pos; i < pos + sendChunkLength; i++) {
//                    streamByteBuf.writeByte(chunkData[i]);
//                }
//                if (pos + sendChunkLength != chunkData.length) {
//                    if (streamId == Common.STREAM_ID) {
//                        streamByteBuf.writeByte((byte) ((4 & 0x3f) | (3 << 6)));
//                    } else {
//                        streamByteBuf.writeByte((byte) ((3 & 0x3f) | (3 << 6)));
//                    }
//                }
//            }
//            pos += sendChunkLength;
//        }
//        sendClient(ctx,streamByteBuf);
//    }

    private static void sendClient(ChannelHandlerContext ctx,ByteBuf streamByteBuf) {
        if (streamByteBuf.readableBytes() > 0) {
            int length = streamByteBuf.readableBytes();
            //if(length > 4096) length = 4096;
            byte[] sendData = new byte[length];
            streamByteBuf.readBytes(sendData);
//            ctx.writeAndFlush(Unpooled.copiedBuffer(sendData));
            ctx.fireChannelRead(sendData); //传递给下一个解码器
        }
        streamByteBuf.release();
    }
}
